﻿// <copyright file="GameProviderCsvExtension.cs" company="Ecole Normale Supérieure">
// Released under GPLv2
// </copyright>
// <summary>Provide CSV import feature to IGameProvider.</summary>

namespace Sqwarea.Persistence.Csv
{
    using System;
    using System.Drawing;
    using System.Globalization;
    using System.IO;
    using LumenWorks.Framework.IO.Csv;

    /// <summary>
    /// Provide CSV import feature to IGameProvider.
    /// </summary>
    public static class GameProviderCsvExtension
    {
        /// <summary>
        /// Import kings dictionnary with a CSV file.
        /// Headers :
        /// KingId ; OpenId ;  LastKingMove ; Position x ; Position y ; AcademyTroops ; x upper corner ; y upper corner ; width ; height ; SquareNumber ; LastAcademyTroopsUpdate
        /// Warning : nickname is set to "nickname" 
        /// </summary>
        /// <param name="gameProvider">The game provider</param>
        /// <param name="file">The CSV file</param>
        public static void ImportKingsFromCsv(this IGameProvider gameProvider, TextReader file)
        {
            using (CsvReader csv = new CsvReader(file, true))
            {
                int fieldCount = csv.FieldCount;

                if (fieldCount != 12)
                {
                    throw new InvalidDataException();
                }

                while (csv.ReadNextRecord())
                {
                    var king = new King(long.Parse(csv[0], Tools.NumberFormat), csv[1], "nickname");
                    king.LastKingMoveDate = DateTimeOffset.Parse(csv[2], CultureInfo.InvariantCulture);
                    king.Position = new Point(
                                              int.Parse(csv[3], Tools.NumberFormat),
                                              int.Parse(csv[4], Tools.NumberFormat));
                    king.AcademyTroops = int.Parse(csv[5], Tools.NumberFormat);
                    king.SquaresRectangle = new Rectangle(
                                                          int.Parse(csv[6], Tools.NumberFormat),
                                                          int.Parse(csv[7], Tools.NumberFormat),
                                                          int.Parse(csv[8], Tools.NumberFormat),
                                                          int.Parse(csv[9], Tools.NumberFormat));
                    king.SquaresNumber = int.Parse(csv[10], Tools.NumberFormat);
                    king.LastAcademyTroopsUpdate = DateTimeOffset.Parse(csv[11], CultureInfo.InvariantCulture);

                    gameProvider.UpdateKing(king);
                }
            }
        }

        /// <summary>
        /// Import kings dictionnary with a CSV file.
        /// Headers :
        /// KingId ; LastKingMove ; Position x ; Position y ; AcademyTroops ; x upper corner ; y upper corner ; width ; height ; SquareNumber ; LastAcademyTroopsUpdate
        /// </summary>
        /// <param name="gameProvider">The game provider</param>
        /// <param name="file">The CSV file</param>
        public static void ImportKingsFromCsv(this IGameProvider gameProvider, string file)
        {
            gameProvider.ImportKingsFromCsv(new StreamReader(file));
        }

        /// <summary>
        /// Import map with a CSV file.
        /// The map begins with coordinate (0,0)
        /// Each square is reprensented by 4 cases in square
        ///     id of King | number of troops
        ///     Path to king (N,W,S,E)    | has king (1 or 0/"")
        /// If "Id of King" and "has king" are empty string, it does not create a square.
        /// If "Id of King" is not an empty string, "number of string" has to be a number.
        /// </summary>
        /// <param name="gameProvider">The game provider</param>
        /// <param name="file">The CSV file</param>
        public static void ImportMapFromCsv(this IGameProvider gameProvider, TextReader file)
        {
            using (CsvReader csv = new CsvReader(file, false))
            {
                int fieldCount = csv.FieldCount;

                if (fieldCount % 2 != 0)
                {
                    throw new InvalidDataException("Not an even number of columns");
                }

                // Current line
                int i = 0;

                while (csv.ReadNextRecord())
                {
                    // First line : id and number of troops
                    for (int j = 0; j < fieldCount / 2; j++)
                    {
                        if (csv[2 * j].Length != 0)
                        {
                            var pos = new Point(j, i);
                            var square = new Square(
                                                    pos,
                                                    int.Parse(csv[2 * j], Tools.NumberFormat),
                                                    int.Parse(csv[(2 * j) + 1], Tools.NumberFormat),
                                                    false);
                            gameProvider.UpdateSquare(square);
                        }
                    }

                    if (!csv.ReadNextRecord())
                    {
                        throw new InvalidDataException("Not an even number of lines");
                    }

                    // Second line : has king ?
                    for (int j = 0; j < fieldCount / 2; j++)
                    {
                        if (csv[(2 * j) + 1].Length != 0)
                        {
                            var pos = new Point(j, i);
                            var square = gameProvider.GetSquareByPosition(pos);
                            square.HasKing = csv[(2 * j) + 1] == "1";
                            var path = Direction.North;
                            switch (csv[2 * j])
                            {
                                case "N":
                                    break;
                                case "S":
                                    path = Direction.South;
                                    break;
                                case "W":
                                    path = Direction.West;
                                    break;
                                case "E":
                                    path = Direction.East;
                                    break;
                                default:
                                    throw new InvalidDataException("Le pathtoking est incorrect : N,S,E,W");
                            }

                            square.PathToKing = path;
                            gameProvider.UpdateSquare(square);
                        }
                    }

                    i++;
                }
            }
        }

        /// <summary>
        /// Import map with a CSV file.
        /// The map begins with coordinate (0,0)
        /// Each square is reprensented by 4 cases in square
        ///     id of King | number of troops
        ///     Path to king (N,W,S,E)    | has king (1 or 0/"")
        /// If "Id of King" and "has king" are empty string, it does not create a square.
        /// If "Id of King" is not an empty string, "number of string" has to be a number.
        /// </summary>
        /// <param name="gameProvider">The game provider</param>
        /// <param name="file">The CSV file</param>
        public static void ImportMapFromCsv(this IGameProvider gameProvider, string file)
        {
            gameProvider.ImportMapFromCsv(new StreamReader(file));
        }
    }
}
